<template>
  <template v-if="!gameTotal.length">
    <div class="chat-content" v-loading="true"></div>
  </template>
  <template v-else>
    <div v-if="!lhc" class="chat-content">
      <div class="grow-[1] !h-0 relative" v-loading="state.loading">
        <template v-if="state.list.length == 0 && !state.loading">
          <div class="w-full h-full flex justify-center items-center">
            <el-empty description="暂无聊天记录" />
          </div>
        </template>
        <virtual-list ref="virtualScrollRef" :list="state.list" @is-scroll-bottom="isScrollBottom">
          <template #header>
            <div class="h-[15px] w-full"></div>
          </template>
          <template #default="{ source }: Item">
            <div
              class="chat-box"
              :class="{
                'mine-chat-box': isMine(source)
              }"
            >
              <template v-if="!isMine(source)">
                <div class="w-[42px] h-[42px]">
                  <img
                    class="w-[42px] h-[42px] bg-[#fff] rounded-[42px]"
                    :src="netPath(source.avatar)"
                  />
                </div>
              </template>
              <div
                class="flex-1 w-0"
                :class="{
                  'mr-[50px] ml-[10px]': !isMine(source),
                  'mr-[10px] ml-[50px]': isMine(source)
                }"
              >
                <div
                  :class="{
                    'flex justify-end': isMine(source)
                  }"
                >
                  <div class="chat-name">
                    {{ source.nick_name }}
                    {{ formatDate(source.time, "HH:mm:ss") }}
                  </div>
                </div>
                <div
                  :class="{
                    'flex justify-end': isMine(source)
                  }"
                >
                  <template
                    v-if="
                      source.msg_type == SocketMsgType.room_text_msg ||
                      source.msg_type == SocketMsgType.room_guessing_msg
                    "
                  >
                    <div class="chat-message" v-html="formatContent(source.content)"></div>
                  </template>
                  <template v-if="source.msg_type == SocketMsgType.img_msg">
                    <div class="chat-message">
                      <div class="bg-[#f5f7fa] flex justify-center w-[220px] h-[144px]">
                        <ImgPreviewDialog :width="600" :src="source.content">
                          <el-image
                            class="h-full w-full"
                            fit="contain"
                            :src="netPath(source.content)"
                          />
                        </ImgPreviewDialog>
                      </div>
                    </div>
                  </template>
                  <template v-if="source.msg_type == SocketMsgType.red_msg">
                    <div class="chat-message !p-0">
                      <div class="relative w-[100px] h-[144px]">
                        <img
                          class="absolute top-0 left-0 w-[100px] h-[144px]"
                          src="@/assets/images/red-bg.png"
                        />
                        <div class="absolute top-[50px] w-full text-center text-[yellow]">红包</div>
                        <div class="absolute top-[70px] w-full text-center text-[yellow]">
                          数量x{{ source.data.Count }}
                        </div>
                      </div>
                    </div>
                  </template>
                </div>
              </div>
              <template v-if="isMine(source)">
                <div class="w-[42px] h-[42px] mt-[5px]">
                  <img
                    class="w-[42px] h-[42px] bg-[#fff] rounded-[42px]"
                    :src="netPath(source?.avatar)"
                  />
                </div>
              </template>
            </div>
          </template>
        </virtual-list>
        <div @click="scrollToBottom" v-if="showChatMore" class="show-chat-more">
          <span v-if="mainState.unreadMessage > 0">{{
            mainState.unreadMessage > 99 ? 99 : mainState.unreadMessage
          }}</span>
          <el-icon class="!text-white !text-[16px]"><ArrowDownBold /></el-icon>
        </div>
      </div>
      <div class="service-fotter">
        <game-footer @send="(msg: string) => handleSend(msg)" />
      </div>
    </div>
    <div v-else class="h-full flex-1 w-0 flex justify-center items-center bg-[#fff]">
      <el-empty description="六合彩彩票无聊天记录" />
    </div>
    <DetailDialog ref="detailDialogRef" :list="detail" />
  </template>
</template>
<script setup lang="ts">
import ImgPreviewDialog from "@/components/img-preview-dialog.vue";
import GameFooter from "./game-footer.vue";
import VirtualList from "@/components/virtual-list.vue";
import DetailDialog from "./detail-dialog.vue";

import $bus from "@/utils/bus";
import { storeToRefs } from "pinia";
import { formatDate, netPath } from "@/utils/common";
import { useGameStore } from "@/store/modules/game";
import { cloneDeep } from "lodash-es";
import { useUserStore } from "@/store/modules/user";
import { reqChatHistory } from "@/api/main";
import { GameCategory, SocketMsgType } from "@/enums";
import { useSocketStore } from "@/store/modules/socket";
import axios from "axios";

interface Item {
  source: GameHistoryMo;
}

interface State {
  loading: boolean;
  page: number;
  pageSize: number;
  list: GameHistoryMo[];
}

const virtualScrollRef = ref();
const detailDialogRef = ref();
const mainState = inject("mainState")! as MainState;
const userStore = useUserStore();
const socketStore = useSocketStore();
const { userInfo, chatToken } = storeToRefs(userStore);
const gameStore = useGameStore();
const { gameTotal } = storeToRefs(gameStore);
const lhc = computed(() => {
  return gameTotal.value?.[mainState.gameActive]?.CategoryId == GameCategory.lhc;
});

const detail = ref<BetDetail[]>([]);
const state = reactive<State>({
  loading: true,
  page: 1,
  pageSize: 100,
  list: []
});
const showChatMore = computed(() => {
  if (!mainState.autoScrollToBottom) {
    return true;
  } else {
    return false;
  }
});
let cancelToken: any = null;
// 获取记录
const getData = async (index: number) => {
  if (gameTotal.value.length == 0) return;
  if (!gameTotal.value[index]) return;
  // 如果有未完成的请求，取消它
  if (cancelToken) {
    cancelToken.cancel("Operation canceled by the user.");
  }
  cancelToken = axios.CancelToken.source();
  state.loading = true;
  try {
    const res = await reqChatHistory(
      {
        LotteryId: gameTotal.value[index].LotteryId,
        Page: 1,
        PageSize: 200
      },
      cancelToken.token
    );
    state.list = res.data || [];
    state.loading = false;
    setTimeout(() => {
      scrollToBottom();
    }, 200);
  } catch (error) {
    state.loading = false;
    console.log(error);
  }
  mainState.loading = false;
};

// 是否为自己
const isMine = (item: GameHistoryMo) => {
  if (
    Number(userInfo.value?.RoomId) === Number(item.user_id) ||
    Number(item.user_id) === 0 ||
    `r_${userInfo.value?.RoomId}` === String(item.user_id)
  ) {
    return true;
  }
  return false;
};

// 标签转义
// function html2Escape(sHtml: string) {
//   var temp: any = document.createElement("div");
//   temp.textContent != null ? (temp.textContent = sHtml) : (temp.innerText = sHtml);
//   var output = temp.innerHTML;
//   temp = null;
//   return output;
// }

// 处理消息体
const formatContent = (content?: string) => {
  if (!content) return "";
  let html = formatString(content);
  return html.replace(/\n/g, "<br />");
};

const formatString = (input: string) => {
  // 匹配字符串开头的 @ 开头并以空格结束的用户名
  const usernamePattern = /^(@\S+)\s/;
  // 匹配 '当前积分:' 后的数字
  const scorePattern = /当前积分:(\d*\.?\d+)/;
  // 匹配 '本次竞猜总分:' 后的数字
  const totalScorePattern = /本次竞猜总分:(\d*\.?\d+)/;
  // 匹配 '最低限额:' 后的数字
  const minPattern = /最低限额:(\d*\.?\d+)/;
  // 匹配 '最高限额:' 后的数字
  const maxPattern = /最高限额:(\d*\.?\d+)/;
  // 匹配 '总元宝:' 后的数字
  const totalYuanbaoPattern = /总元宝:(\d*\.?\d+)/;
  // 匹配 '汇总：' 后的数字
  const summaryPattern = /(汇总：)(\d*\.?\d+)/g;
  //替换 '第x名[' 和 '/' 之间的数字或中文
  const multiRankPattern = /(\[)([\S\s]*?\/\d+\.?\d*)(\])/g;

  // 替换用户名
  const formattedUsername = input.replace(usernamePattern, "<span class='text-blue'>$1</span> ");
  // 替换当前积分
  const formattedScore = formattedUsername.replace(
    scorePattern,
    "当前积分:<span class='text-red'>$1</span>"
  );
  // 替换本次竞猜总分
  const formattedTotalScore = formattedScore.replace(
    totalScorePattern,
    "本次竞猜总分:<span class='text-red'>$1</span>"
  );
  // 替换最低限额
  const minScore = formattedTotalScore.replace(
    minPattern,
    "最低限额:<span class='text-red'>$1</span>"
  );
  // 替换最高限额
  const maxScore = minScore.replace(maxPattern, "最高限额:<span class='text-red'>$1</span>");
  // 替换总元宝
  const totalYuanbao = maxScore.replace(
    totalYuanbaoPattern,
    "总元宝:<span class='text-red'>$1</span>"
  );
  // '汇总：' 后的数字
  const summary = totalYuanbao.replace(summaryPattern, "$1<span class='text-red'>$2</span>");
  // 替换结尾的数字
  const formattedEnd = summary.replace(multiRankPattern, function (_match, p1, p2, p3) {
    const parts = p2.split(" ");
    const formattedParts = parts.map((part: string) =>
      part.replace(/(\/)(\d+)/, "$1<span class='text-red'>$2</span>")
    );
    return p1 + formattedParts.join(" ") + p3;
  });
  const outtext = formattedEnd.replace(
    /<a\s+(data='[^']*')>.*?<\/a>/g,
    `<span class="text-blue detail cursor-pointer" $1>注单详情</span>`
  );
  return outtext;
};

// 滚动到底部
const scrollToBottom = () => {
  virtualScrollRef.value?.scrollToBottom();
  mainState.unreadMessage = 0;
  nextTick(() => {
    setDomClick();
  });
};

// 设置为是否滚动到底部
const isScrollBottom = (flag: boolean) => {
  mainState.autoScrollToBottom = flag;
};

// 发送消息
const handleSend = (content: string) => {
  const roomName = `${userInfo.value?.RoomId}_${gameTotal.value[mainState.gameActive].LotteryId}`;
  const sendData = {
    token: chatToken.value,
    roomName, // 房间ID
    content: content,
    msgType: 2,
    width: 0,
    height: 0,
    sendType: "PUBLIC",
    customize: "",
    thumb: ""
  };
  socketStore.client?.emit("send_msg", sendData);
};

// 处理注单点击事件
const setDomClick = () => {
  document.querySelectorAll(".chat-message .detail").forEach((dom: any) => {
    if (dom) {
      dom.onclick = () => {
        detail.value = JSON.parse(dom.getAttribute("data"));
        nextTick(() => {
          detailDialogRef.value?.open();
        });
      };
    }
  });
};

const watchSocket = () => {
  // 监听房间消息
  $bus.on("room-msg", async (data: GameHistoryMo) => {
    let obj = cloneDeep(data);
    let messages = cloneDeep(state.list);
    messages.push({
      ...obj
    });
    if (messages.length >= 600) {
      messages = messages.slice(200, messages.length + 1);
    }
    state.list = cloneDeep(messages);
    await nextTick();
    if (showChatMore.value) {
      mainState.unreadMessage++;
    } else {
      setTimeout(() => {
        scrollToBottom();
      }, 500);
    }
  });
  $bus.on("game-switch", () => {
    getData(mainState.gameActive);
  });
  $bus.on("updata-history-list", () => {
    getData(mainState.gameActive);
  });
};

onMounted(() => {
  watchSocket();
});
onUnmounted(() => {
  $bus.off("room-msg");
  $bus.off("game-switch");
  $bus.off("updata-history-list");
});
</script>
<style scoped>
.chat-content {
  @apply h-full flex-1 w-0 bg-[#fff] flex flex-col justify-between;
  transition: all 0.3s ease;
}
.service-fotter {
  @apply h-[105px] w-full bg-[#fff];
}
.chat-name {
  @apply h-[18px] leading-[18px] px-[5px] rounded-[4px] inline-block text-[14px] mb-[4px];
  color: #878c94;
}
.chat-message {
  @apply bg-[#f4f7f8] inline-block p-[10px] mb-[10px] rounded-[6px] relative text-[14px] max-w-[450px];
  word-break: break-all;
  color: #666;
}
.show-chat-more {
  @apply absolute bottom-[5px] right-[15px] z-[50] cursor-pointer;
  @apply h-[40px] w-[40px] bg-[var(--el-color-primary)] rounded-[20px];
  @apply flex flex-col justify-center items-center text-white text-[14px];
}
</style>
<style lang="scss" scoped>
.chat-box {
  margin: 0 10px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  overflow: hidden;
  // &:first-child {
  //   margin-top: 10px;
  // }
}
.mine-chat-box {
  .chat-message {
    background-color: #dcf8c6;
  }
}
</style>
